﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace Al.UI.Controls
{
    public class CometServer
    {
        private static object _contextLock;
        private static object _messageLock;
        private static bool _keepRunning = true;
        private static Dictionary<string, CometSession> _cometSessionList;
        private static Dictionary<string, CometController> _cometControllerList;
        private static Dictionary<string, object> _messageList;
        private static readonly int WAIT_TIMEOUT = 120000;
        private static Thread _messagePumpThread;

        static CometServer()
        {
            _contextLock = new object();
            _messageLock = new object();
            _cometSessionList = new Dictionary<string, CometSession>();
            _cometControllerList = new Dictionary<string, CometController>();
            _messageList = new Dictionary<string, object>();
            _messagePumpThread = new Thread(new ThreadStart(MessageProc));
            _messagePumpThread.Start();
        }

        private static void MessageProc()
        {
            lock (_contextLock)
            {
                while (_keepRunning)
                {
                    Monitor.Wait(_contextLock);
                    foreach (CometSession session in _cometSessionList.Values)
                    {
                        CometController controller = _cometControllerList[session.SessionID];
                        if (_messageList.ContainsKey(session.SessionID))
                            controller.Invalidate();
                    }
                }
            }
        }

        public static void WaitForUpdate(CometSession session)
        {
            session.CometContext.UpdateEvent.WaitOne(WAIT_TIMEOUT, false);
        }

        public static void RegisterPage(string sessionID)
        {
            lock (_contextLock)
            {
                CometSession session = CometSession.GetNewSession();
                _cometSessionList[session.SessionID] = session;

                CometController controller = new CometController(session.SessionID);
                _cometControllerList[session.SessionID] = controller;
            }
        }

        public static CometSession GetSession(string sessionID)
        {
            if (_cometSessionList.ContainsKey(sessionID))
                return _cometSessionList[sessionID];
            return null;
        }

        public static CometController GetCometController()
        {
            string sessionID = CometSessionStore.CurrentSessionID;
            if (sessionID != null)
                return _cometControllerList[sessionID];
            return null;
        }

        public static CometController GetCometController(CometSession session)
        {
            if (_cometControllerList.ContainsKey(session.SessionID))
                return _cometControllerList[session.SessionID];
            return null;
        }

        public static void Invalidate(CometSession session)
        {
            lock (_contextLock)
            {
                session.CometContext.UpdateEvent.Set();
            }
        }

        public static void NotifyMessageRecieved(CometController controller, object data)
        {
            lock (_messageList)
            {
                _messageList[controller.SessionID] = data;
                Monitor.PulseAll(_contextLock);
            }
        }
    }
}
